#include "fitness.h"

//classic trap function used by goldberg for binary strings
float ftrap(int number_of_1s, int function_trap_size)
{
	float d= (float)1/(float)function_trap_size;

	if(number_of_1s == function_trap_size)
	{
		return 1;
	}
	else
	{
		return 1 - d - number_of_1s*((1-d)/(function_trap_size-1));
	}
}

//classic deception function used by goldberg
float fdeception(int* chromossome, int generation, long array_size)
{
	int i;

	//this variable could change at our will
	int function_trap_size= 4;

	float fitness=0;

	for(i=0;i<array_size;)
	{
		int counter;
		int number_of_1s=0;

		for(counter=0;counter<function_trap_size&&counter+i<array_size;counter++)
		{
			number_of_1s+=chromossome[i+counter];
		}

		i+=counter;

		fitness+= ftrap(number_of_1s, function_trap_size);
	}

	return fitness;
}

/**
 * present in the article: "A matrix approach for finding extreme problems with modularity,hierarchy and overlap"
 *
 * Utiliza blocos de tamanho 5 com overlap de 2, sendo que
 * o ultimo bloco é formado por parte do final do cromossomo
 * e parte do inicio, formando um ciclo.
 *
 * @param n	Tamanho do cromossomo
 * @param gen
 * @param x	chromosome
 */
float trap5_cyclic(int *x, int gen, long n)
{
    const int k	      = 5;
    const int overlap = 2;
    const int step    = k - overlap;

    float fitness = 0.0;

    for (int i = 0; i < n; i += step)
    {
	short u = 0;

	u  = x[(i)   % n];
	u += x[(i+1) % n];
	u += x[(i+2) % n];
	u += x[(i+3) % n];
	u += x[(i+4) % n];


	if (u < 5)
	    fitness += (4 - u);
	else
	    fitness += 5;
    }

    return fitness;
}


float test(int* chromossome, int generation, long array_size)
{
	int i;
	int value=0;
	
	//printf("executed\n");

	for(i=0;i<array_size;++i)
	{
		value+= chromossome[i];
	}

	
	if(chromossome[13]==0&&chromossome[12]==0&&chromossome[11]==0&&chromossome[16]==0&&chromossome[17]==0)
	{
		value*=2;
	}
	
	

	return value;
}

/*
static Fitness fitnessDesc[numFitness] = {
  {"ONEMAX",&onemax,&areAllGenesOne,NULL,NULL},
  {"Quadratic 0.9 0 0 1",&quadratic,&areAllGenesOne,NULL,NULL},
  {"Fitness-3 DECEPTIVE",&f3deceptive,&areAllGenesOne,NULL,NULL},
  {"5-ORDER TRAP (Illinois Report No. 95008)",&trap5,&areAllGenesOne,NULL,NULL},
  {"3deceptive Bipolar",&f3deceptiveBipolar,&areBlocks6ZeroOrOne,NULL,NULL},
  {"3deceptive (OVERLAPPING in 1bit)",&f3deceptiveOverlapping,&areAllGenesOne,NULL,NULL},
};*/

// ================================================================================
//
// name:          onemax
//
// function:      computes the value of onemax (or bit-count) function
//
// parameters:    x............a binary string
//                n............the length of a string
//
// returns:       (float) the sum of input bits
//
// ================================================================================

float onemax(int *x, int gen, long n)
{
   int s;

   s=0;

   for (register int i=0; i<n; i++)
       s += x[i];

   return (float) s;
}

// ================================================================================
//
// name:          quadratic
//
// function:      computes the value of quadratic function
//
// parameters:    x............a binary string
//                n............the length of a string
//
// returns:       (float) sum_{i=0}^{n/2-1}{f2(x[2i],x[2i+1]}, where f2(0,0)=0.9,
//                f2(1,1)=1, and f(0,1)=f(1,0)=0
//
// ================================================================================

float quadratic(int *x, int gen, long n)
{
  char a,b;
  float f;
  register int i;

  f = 0;

  for (i=0; i<n;)
    {
      a = x[i++];
      b = x[i++];
      
      if (a==0)
	if (b==0)
	  f += 0.9;
	else
	  f += 0;
      else
	if (b==0)
	  f += 0;
	else
	  f += 1;
    }

  return f;
}

// ================================================================================
//
// name:          f3deceptive
//
// function:      computes the value of 3-deceptive function
//
// parameters:    x............a binary string
//                n............the length of a string
//
// returns:       (float) sum_{i=0}^{n/3-1}{f3(x[3i],x[3i+1],x[3i+2]}, where 
//                f3(0,0,0)=0.9, f3(0,0,1)=f3(0,1,0)=f3(1,0,0)=0.8,
//                f3(0,1,1)=f3(1,0,1)=f3(1,1,0)=0, and f3(1,1,1)=1
//
// ================================================================================

float f3deceptive(int *x, int gen, long n)
{
  float f;
  char s;
  register int i;

  f = 0;

  for (i=0; i<n;)
    {
      s  = x[i++];
      s += x[i++];
      s += x[i++];

      if (s==0)
	f+=0.9;
      else
      if (s==1)
	f+=0.8;
      else
      if (s==3)
	f+=1;
    }

  return f;
}

// ================================================================================
//
// name:          trap5
//
// function:      computes the value of trap-5 function
//
// parameters:    x............a binary string
//                n............the length of a string
//
// returns:       (float) the value of a trap5 function
//
// ================================================================================

float trap5(int *x, int gen, long n)
{
  int s;
  char u;
  register int i;

  s = 0;

  for (i=0; i<n; )
    {
      u  = x[i++];
      u += x[i++];
      u += x[i++];
      u += x[i++];
      u += x[i++];
      
      if (u<5)
	s += 4-u;
      else
	s += 5;
    };

   return (float) s;
}



float password2(int* x, int gen, long array_size)
{
    int  s = 0;
    char u = 0;

    const int k = 5;

    for (int i = 0; i < array_size; i += k)
    {
        u  = x[i];
        u += x[i + 1];
        u += x[i + 2];
        u += x[i + 3];
        u += x[i + 4];

        s += (u == 1 || u == 4) ? 5 : 0;
    }

    return (float) s;
}

// ================================================================================
//
// name:          f3deceptiveBipolar
//
// function:      computes the value of 3-deceptive bipolar function
//
// parameters:    x............a binary string
//                n............the length of a string
//
// returns:       (float) the value of a 3-deceptive bipolar function
//
// ================================================================================

float f3deceptiveBipolar(int *x, int gen, long n)
{
  float f;
  char s;
  register int i;
  
  f = 0;
  
  for (i=0; i<n;)
    {
      s  = x[i++];
      s += x[i++];
      s += x[i++];
      s += x[i++];
      s += x[i++];
      s += x[i++];

      s = abs(s-3);

      if (s==0)
	f+=0.9;
      else
	if (s==1)
	  f+=0.8;
	else
	  if (s==3)
	    f+=1;
    }

  return f;
}

// ================================================================================
//
// name:          f3deceptiveOverlapping
//
// function:      computes the value of 3-deceptive function overlapped in 1 bit
//                in a chain-like fashion
//
// parameters:    x............a binary string
//                n............the length of a string
//
// returns:       (float) the value of a 3-deceptive function with overlapping
//
// ================================================================================

float f3deceptiveOverlapping(int *x, int gen, long n)
{
  float f;
  char s;
  register int i;

  f = 0;

  for (i=0; i<n-1;)
    {
      s  = x[i++];
      s += x[i++];
      s += x[i];

      if (s==0)
	f+=0.9;
      else
      if (s==1)
	f+=0.8;
      else
      if (s==3)
	f+=1;
    }

  return f;
}
